/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#if !defined(AFX_PGLARCHIVE_H__5485A0BB_1EDA_458E_B1BC_EB31FF6C53D0__INCLUDED_)
#define AFX_PGLARCHIVE_H__5485A0BB_1EDA_458E_B1BC_EB31FF6C53D0__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000



class CPGLRegion;
#ifndef PGL_CPGLREGION_SMARTPTR_DEF
	#define PGL_CPGLREGION_SMARTPTR_DEF
	PGL_DECLARE_SMARTPTR( CPGLRegion );
#endif

/*! \brief A CArchive interface

	This class provides I/O methods such as a CArchive interface, or XML loading and saving.

\par Raster output format

- BMP: No parameters.
- PNG: No parameters.
- JPEG: 
	-# Quality: from 0 (low quality, good compression) to 100 (high quality, poor compression). See SetJPEGQuality, GetJPEGQuality. Default is 75.
	-# Transformation: flipping, rotations. See SetJPEGTransformation, GetJPEGTransformation. Default is none.
- TIFF:
	-# Compression type. Available compression type are LZW, RLE, CITT13 and CITT14. See SetTIFFCompression, GetTIFFCompression. Default is none.
	-# ColorDepth. Number of color bits per pixel:1, 4, 8, 24 or 32. See SetTIFFColorDepth, GetTIFFColorDepth. Default is 24.
- WMF: No parameters.
- EMF: No parameters.
- EPS: No parameters.
- SVG: No parameters.

\par Exporting to file or IStream
You can raster to file using the above raster formats. The formats BMP,PNG,JPEG and TIFF can also be saved to
IStream.

\code
// a region
CPGLRegion* pRegion;

// creating archive
CPGLArchive ar( pRegion);

// changing quality
ar.SetJPEGQuality( 50 );

// exporting to jpeg, the .jpg is automatically appended
ar.Export( FileFormatJPG, _T("filename"), CPGLPointU( 300,300) );

\endcode

\par Exporting to clipboard
You can export a CPGLRegion to the clipboard as
	- a windows bitmap,
	- a windows metafile.

\code
// a region
CPGLRegion* pRegion;

// creating archive
CPGLArchive ar( pRegion);
// exporting to clipboard as bitmap
ar.ExportToClipBoard();
\endcode

\par Serializing to XML
PGL charts are serialized in XML. You can load/save them from files or string using Load and Save functions.

\par Serializing to CArchive
PGLArchive is an interface between PGL and CArchive. You can use it as any usual MFC object:


\code
// a region
CPGLRegion* pRegion;

// creating archive
CPGLArchive ar( pRegion);

// an archive...
CArchive archive;

// serializing the region
ar.Serialize( archive );
\endcode

\par Zipping

  You can turn on/off zipping for serialization (see SetZipping and IsZipping).
  Using ZLib 1.1.4.

  \todo Make JPEG transformations work
  \todo Make TIFF options work

  \ingroup PGLBasicGroup
*/
class PGLCORE_EXT_CLASS CPGLArchive
{
public:
	//! \name Constructors
	//@{
	/*! Default constructor

	\param pRegion CPGLRegion to store/load
	\param pGfxInterface GfxInterface to store/load rendering options (optional)
	*/
	CPGLArchive(CPGLRegionStPtr pRegion = CPGLRegionStPtr(), gfxinterface::CGfxInterface* pGfxInterface = NULL /* Optional */);
	/*! Serializes the pRegion object with CArchive ar

	\param pRegion CPGLRegion to store/load
	\param ar the famous CArchive
	\param pGfxInterface GfxInterface to store/load rendering options (optional)
	*/
	CPGLArchive(CPGLRegionStPtr pRegion, CArchive& ar, gfxinterface::CGfxInterface* pGfxInterface /* Optional */);
	//! destructor
	virtual ~CPGLArchive();
	//@}

	//! \name Loading and saving to XML
	//@{
	//! Loads data from XML file
	bool Load(LPCTSTR szFileName);
	//! Saves data to XML file
	bool Save(LPCTSTR szFileName);
	//! Loads data from XML string
	bool LoadString(LPCTSTR szXMLString);
	//! Save data to XML string
	bool SaveString(CString& sXMLString);
	//@}

	//! \name Zipping
	//@{
	//! returns true if zipping xml (default is false)
	bool IsZipping() const					{	return m_bZipping;};
	//! sets zipping state
	void SetZipping( bool bEnable = true)	{	m_bZipping = bEnable;};
	//@}

    // \brief Render options
    //@{
    //! Returns the current render option
    DWORD GetRenderOption() const;
    //! Sets the rendering option
    void SetRenderOption(DWORD eo_);
    //@}

	//! \name JPEG Options
	//@{

	/*! JPEG flags

	Note  If the width and height of a JPEG image are multiples of 16, 
	you can apply any of the transformations 
	(for example, 90-degree rotation) without loss of information.
	*/
	enum EJPEGTransform
	{
		//! specifies no transformation
		JPEGTransformNone=0,
		//! specifies lossless 90-degree clockwise rotation
		JPEGTransformRotate90=Gdiplus::EncoderValueTransformRotate90,
		//!  specifies lossless 180-degree rotation
		JPEGTransformRotate180=Gdiplus::EncoderValueTransformRotate180,
		//! specifies lossless 270-degree clockwise rotation
		JPEGTransformRotate270=Gdiplus::EncoderValueTransformRotate270,
		//! specifies a lossless horizontal flip
		JPEGTransformFlipHorizontal=Gdiplus::EncoderValueTransformFlipHorizontal,
		//! specifies a lossless vertical flip. 
		JPEGTransformFlipVertical=Gdiplus::EncoderValueTransformFlipVertical
	};
	
	//! sets the jpeg transform, default is none
	void SetJPEGTransform( EJPEGTransform eTransform )	{	m_eJPEGTransform = eTransform;};
	//! return the current jpeg transform
	EJPEGTransform GetJPEGTransform() const				{	return m_eJPEGTransform; };

	/*! \brief Sets the quality

	Sets the quality of the JPEG from 0 (low quality, good compression) to 100 (high quality, low compression).
	*/
	void SetJPEGQuality( long lQuality )					{	m_lJPEGQuality = __min( 100, __max( 0, lQuality ));};
	//! return the jpeg quality
	long GetJPEGQuality() const								{	return m_lJPEGQuality;};
	//@}

	//! \name TIFF Options
	//@{
	//! TIFF Compression types
	enum ETIFFCompression
	{
		//! specifies no compression, this is the default value
		TIFFCompressionNone=0,
		//! specifies the LZW compression method. 
		TIFFCompressionLZW=1, 
		//! specifies the CCITT3 compression method. 
		TIFFCompressionCCITT3=2,
		//! specifies the CCITT4 compression method. 
		TIFFCompressionCCITT4=3,
		//! specifies the RLE compression method.
		TIFFCompressionRle=4
	};

	//! TIFF Colordepth
	enum ETIFFColorDepth
	{
		//! specifies a 1 bit color depth
		TIFFColorDepth1=0, 
		//! specifies a 4 bit color depth
		TIFFColorDepth4=1,
		//! specifies a 8 bit color depth
		TIFFColorDepth8=2,
		//! specifies a 24 bit color depth, this is the default value
		TIFFColorDepth24=3,
		//! specifies a 32 bit color depth
		TIFFColorDepth32=4
	};

	//! set the TIFF compression
	void SetTIFFCompression( ETIFFCompression eCompress )		{	m_eTIFFCompression=eCompress; };
	//! return the TIFF Compression
	ETIFFCompression GetTIFFCompression() const					{	return m_eTIFFCompression;};
	//! set the TIFF color depth
	void SetTIFFColorDepth( ETIFFColorDepth eColordepth )		{	m_eTIFFColorDepth=eColordepth; };
	//! return the TIFF colordepth 
	ETIFFColorDepth GetTIFFColorDepth() const					{	return m_eTIFFColorDepth;};
	
	//@}

	//! \name Export functions
	//@{
	//! Available file formats
	enum EFileFormat
	{
		//! Portable network graphics
		FileFormatPNG=1,
		//! JPEG
		FileFormatJPG=2,
		//! Tagged-image file format
		FileFormatTIFF=3,
		//! Windows bitmap
		FileFormatBMP=4,
		//! Specifies that all of the records in the metafile are EMF records, which can be displayed by GDI or GDI+. 
		FileFormatEMFOnly=5,
		//! Specifies that all of the records in the metafile are EMF+ records, which can be displayed by GDI+ but not by GDI. 
		FileFormatEMFPlusOnly=6,
		//! Specifies that all EMF+ records in the metafile are associated with an alternate EMF record. Metafiles of type EmfTypeEmfPlusDual can be displayed by GDI or by GDI+
		FileFormatEMFPlusDual=7,
		//8 Encapsulated postscript
		FileFormatEPS=8,
		//! Scalable vector graphics
		FileFormatSVG=9,
		//! Scalable vector graphics, zipped
		FileFormatSVGZ=10
	};

	/*! \brief Exporting functions to differents

	\param eFileFormat, enum describing the file format
	\param szFileName file name, the extension determines the type of output
	\param hDC [optional] current dc
	\param dim [optional] dimension of the output
	\param bZoomAll [optional] true if a zoom all operation is done
	
	  The available outputs are described in the EFileFormat
	*/
	bool ExportToFile( EFileFormat eFileFormat, LPCTSTR szFileName, const CPGLPointU& dim = CPGLPointU(600,480), HDC hDC = NULL, bool bZoomAll=false);

	/*! \brief Saves data to stream

	This method exports the chart to a IStream. 

	\param eFileFormat, enum describing the file format
	\param pIStream, pointer to valid IStream object
	\param hDC [optional] current dc
	\param dim [optional] dimension of the output
	\param bZoomAll [optional] true if a zoom all operation is done

	This method does not work for EPS and SVG
	*/
	bool ExportToStream( EFileFormat eFileFormat, IStream* pIStream, const CPGLPointU& dim = CPGLPointU(600,480), HDC hDC = NULL, bool bZoomAll=false);

	/*! \brief Draws region to bitmap.

	\param pImage pointer to image where the plot has to be written
	\param hDC [optional] handle to the current device context
	\param bZoomAll [optional] true if a zoom all operation is done, default is false
	*/
	bool ExportToImage( 
		Gdiplus::Image* pImage, 
		HDC hDC = NULL, 
		bool bZoomAll = false
		);

	bool ExportToBitmap(
		size_t width_,
		size_t height_,
		size_t stride_,
		size_t bpp_,
		unsigned char* bits_,
		HDC hDC = NULL, 
		bool bZoomAll = false
		);

	/*! \brief Draws region to metafile.

	\param pImage pointer to image where the plot has to be written
	\param hDC [optional] handle to the current device context
	\param bZoomAll [optional] true if a zoom all operation is done, default is false
	*/
	bool ExportToMetafile(
		Gdiplus::Metafile* metafile, 
		const CPGLPointU& dim, 
		HDC hDC, 
		bool bZoomAll=false );

	/*! Export to string

	\param string the string that will contain the chart
	\param dim [optional] dimension of the output
	\param bZoomAll [optional] true if a zoom all operation is done
	\param hDC [optional] handle to the current device context

	This method works only for EPS and SVG.
	*/
	bool ExportToString( 
		EFileFormat eFileFormat, 
		CString& string, 
		const CPGLPointU& dim = CPGLPointU(600,480),  
		bool bZoomAll = false, 
		HDC hDC = NULL
		);

	/*! \brief Types of clipboard output
	*/
	enum EClipBoardType
	{
		//! To metafile (emf)
		ClipBoardMetafile = 0,
		//! To windows bitmap (bmp)
		ClipBoardBitmap = 1
	};
	/*! \brief Export to clipboard

	Exports chart to clipboard as
		- metafile,
		- bitmap
	\param eClipBoardType, type of output (see EClipBoardType)
	\param [optional] bZoomAll true if a zoom all operation is done
	\param [optional] dim, dimension in pixels of the ouput bitmap
	\param [optional] hWnd, current window handle,
	*/
	bool ExportToClipBoard(EClipBoardType eClipBoardType = ClipBoardBitmap, bool bZoomAll = false,const CPGLPointU& dim = CPGLPointU(640,480), HWND hWnd = NULL);
	//@}

	//! Import function
	//@{
	/*! \brief Imports an image from stream

	This method import an image from an input stream. The supported formats depends on the codec installed on your
	machine. You can check the available formats using the TestPGL application (under the menu Misc->Decoders)

	\param IStream, the stream opened for reanding containing the metafile
	\param bTryUsingGDI [optional] true if it tries to load the stream as metafile first
	\return pointer to a new Gdiplus::Image if succeded, FALSE otherwize

	If bTryUsingGDI is set to true, CPGLArchive tries to load the image as a enhanced metafile first using
	the GDI methods (SetEnhMetaFileBits). If it succeds, the loaded image is of type ImageTypeMetafile,
	otherwize all the images will be of the type ImageTypeBitmap.

	Note that you can check wether load an image as metafile succeded by using Image.GetType() method.
	*/
	static Gdiplus::Image* ImportFromStream( IStream* pIStream, bool bTryUsingGDI = true); 
	//@}

	//! \name Setters and getters
	//@{
	//! Attaches the object to be serialized to the archive
	void SetRegion(CPGLRegionStPtr pRegion);
	//! returns pointer to region
	CPGLRegionStPtr GetRegion()											{	return m_pRegion;};	
	//! Sets creator (used in export)
	void SetCreator(LPCTSTR szCreator)									{	m_sCreator=szCreator;};
	//! Sets title (used in export)
	void SetTitle(LPCTSTR szTitle)										{	m_sTitle=szTitle;};
	//! return text overlay, const
	LPCTSTR GetTextOverlay() const										{	return m_sTextOverlay;};
	//! sets text overlay
	void SetTextOverlay(LPCTSTR szTextOverlay)							{	m_sTextOverlay = szTextOverlay;};
	//! return text overlay, const
	const LOGFONT& GetTextOverlayFont() const							{	return m_lfTextOverlay;};
	//! sets text overlay
	void SetTextOverlayFont(const LOGFONT& lf)							{	m_lfTextOverlay = lf;};
	//@}

	//! \name FileDialog helpers
	//@{
	//! Add file extension depending on filename, current extension and selected filter
	static void ProcessFileNameExt( CString& szFileName,  const CString& szFileExt, EFileFormat eFileFormat);
	//! returns CFileDialog filter
	static CString GetFileDialogFilter();
	//@}

	//! \name Serialization methods
	//@{
	//! returns true if loading
	bool IsLoading() const			{	return !m_bStoring;};
	//! returns true if storing
	bool IsStoring() const			{	return m_bStoring;};
	//! Serialization to CArchive
	void Serialize( CArchive& ar);
	//@}

	//! Internal function
	void* GetMarkup()	{	return m_pXml;};

protected:
	bool ExportMetafileToStream( EFileFormat eFileFormat, IStream* pIStream, const CPGLPointU& dim, HDC hDC, bool bZoomAll);

private:
	//! \name Attributes
	//@{
	//! pointer to the object to be serialized
	CPGLRegionStPtr m_pRegion;
	//! title of export (used for export where a title field exists)
	CString m_sTitle;
	//! creator of export (used for export where a title field exists)
	CString m_sCreator;
	//! Text overlay
	CString m_sTextOverlay;	
	//! Text font
	LOGFONT m_lfTextOverlay;
	//! zipping
	bool m_bZipping;
	//! jpeg transform
	EJPEGTransform m_eJPEGTransform;
	//! jpeg quality
	long m_lJPEGQuality;
	//! tiff compression
	ETIFFCompression m_eTIFFCompression;
	//! tiff color depth
	ETIFFColorDepth m_eTIFFColorDepth;
	//! Pointer to CMarkupArchive object
	void* m_pXml;
	//! Pointer to CGfxInterface
	gfxinterface::CGfxInterface* m_pGfxInterface;
	bool m_bStoring;
	ULONG m_ulJPEGTransform;
    DWORD m_eRenderOption;
	//@}

	void SerializeGfx();
	Gdiplus::EncoderParameters* GetEncoderParameters(EFileFormat eFileFormat);
};

#endif // !defined(AFX_PGLARCHIVE_H__5485A0BB_1EDA_458E_B1BC_EB31FF6C53D0__INCLUDED_)
